package com.baidu.iit.pxp.behavior;

import com.baidu.iit.pvm.ActivityException;
import com.baidu.iit.pvm.ActivityIllegalArgumentException;
import com.baidu.iit.pvm.delegate.ActivityExecution;
import com.baidu.iit.pvm.process.ActivityImpl;
import com.baidu.iit.pxp.BpmnError;

/**
 * User: huangweili
 * Date: 14-4-27
 * Time: 上午9:19
 */
public class SequentialMultiInstanceBehavior extends MultiInstanceActivityBehavior {

    public SequentialMultiInstanceBehavior(ActivityImpl activity, AbstractBpmnActivityBehavior innerActivityBehavior) {
        super(activity, innerActivityBehavior);
    }

    protected void createInstances(ActivityExecution execution) throws Exception {
        int nrOfInstances = resolveNrOfInstances(execution);
        if (nrOfInstances <= 0) {
            throw new ActivityIllegalArgumentException("Invalid number of instances: must be positive integer value"
                    + ", but was " + nrOfInstances);
        }

        setLoopVariable(execution, NUMBER_OF_INSTANCES, nrOfInstances);
        setLoopVariable(execution, NUMBER_OF_COMPLETED_INSTANCES, 0);
        setLoopVariable(execution, getCollectionElementIndexVariable(), 0);
        setLoopVariable(execution, NUMBER_OF_ACTIVE_INSTANCES, 1);
        logLoopDetails(execution, "initialized", 0, 0, 1, nrOfInstances);

        executeOriginalBehavior(execution, 0);
    }


    public void leave(ActivityExecution execution) {
        int loopCounter = getLoopVariable(execution, getCollectionElementIndexVariable()) + 1;
        int nrOfInstances = getLoopVariable(execution, NUMBER_OF_INSTANCES);
        int nrOfCompletedInstances = getLoopVariable(execution, NUMBER_OF_COMPLETED_INSTANCES) + 1;
        int nrOfActiveInstances = getLoopVariable(execution, NUMBER_OF_ACTIVE_INSTANCES);

        if (loopCounter != nrOfInstances && !completionConditionSatisfied(execution)) {
            callActivityEndListeners(execution);
        }

        setLoopVariable(execution, getCollectionElementIndexVariable(), loopCounter);
        setLoopVariable(execution, NUMBER_OF_COMPLETED_INSTANCES, nrOfCompletedInstances);
        logLoopDetails(execution, "instance completed", loopCounter, nrOfCompletedInstances, nrOfActiveInstances, nrOfInstances);

        if (loopCounter == nrOfInstances || completionConditionSatisfied(execution)) {
            super.leave(execution);
        } else {
            try {
                executeOriginalBehavior(execution, loopCounter);
            } catch (BpmnError error) {
                throw error;
            } catch (Exception e) {
                throw new ActivityException("Could not execute inner activity behavior of multi instance behavior", e);
            }
        }
    }

    @Override
    public void execute(ActivityExecution execution) throws Exception {
        super.execute(execution);

        if(innerActivityBehavior instanceof SubProcessActivityBehavior) {
            // ACT-1185: end-event in subprocess may have inactivated execution
            if(!execution.isActive() && execution.isEnded() && (execution.getExecutions() == null || execution.getExecutions().size() == 0)) {
                execution.setActive(true);
            }
        }
    }

}
